home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libcan / canbrush.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  4.8 KB  |  263 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    canbrush -
  19.  *        Draw a brush onto the canvas.
  20.  *
  21.  *                Paul Haeberli - 1991
  22.  *
  23.  *    exports
  24.  *
  25.     void drawbrush(dest,fx,fy)
  26.     void getcircpos(x,y);
  27.     float qrand();
  28.     int getqrandstate();
  29.     int setqrandstate(s);
  30.     setcurwidth(w);
  31.  *
  32.  */
  33. #include "values.h"
  34. #include "math.h"
  35. #include "stdio.h"
  36. #include "canvas.h"
  37.  
  38. extern float can_curalpha;
  39. extern float can_curalphascale;
  40.  
  41. #define RANDTABSIZE    (2*1020)
  42.  
  43. float frand();
  44. static freebrush();
  45. static brush *makebrush();
  46.  
  47. static brush *curbrush;
  48. static float curwidth;
  49. static float curbwidth, curbalpha;
  50. static float *circpos;
  51. static float *randtab;
  52. static float randfirsted;
  53. static int qp;
  54.  
  55. /*
  56.  *    draw brushes
  57.  *
  58.  */
  59. static updatebrush(width,alpha)
  60. float width, alpha;
  61. {
  62.     if (width != curbwidth || alpha != curbalpha) {
  63.     if (curbrush)
  64.         freebrush(curbrush);
  65.     curbrush = makebrush(width,width,alpha);
  66.     curbwidth = width;
  67.     curbalpha = alpha;
  68.     }
  69. }
  70.  
  71. static float brushfunc(xpos,ypos)
  72. float xpos, ypos;
  73. {
  74.     float rad, val;
  75.  
  76.     rad = 2.0*fsqrt(xpos*xpos+ypos*ypos);
  77.     if(rad<1.0) 
  78.     val = 0.5+(cos(M_PI*rad)/2.0);
  79.     else
  80.     val = 0.0;
  81.     return 1.3*val;
  82. }
  83.  
  84. static freebrush(b)
  85. brush *b;
  86. {
  87.     myfree(b->mat);
  88.     myfree(b);
  89. }
  90.  
  91. static int quant255(val)
  92. float val;
  93. {
  94.     if (val<0.0)
  95.     val = 0.0;
  96.     if (val>1.0)
  97.     val = 1.0;
  98.     return (val*255.0)+0.50;
  99. }
  100.  
  101. static float limit(val)
  102. float val;
  103. {
  104.     if (val<0.0)
  105.     return 0.0;
  106.     if (val>1.0)
  107.     return 1.0;
  108.     return val;
  109. }
  110.  
  111. static int noiseround(v)
  112. float v;
  113. {
  114.     return ffloor(v+(0.99*(qrand()+0.5)));
  115. }
  116.  
  117. static brush *makebrush(dx,dy,alpha)
  118. float dx, dy, alpha;
  119. {
  120.     brush *b;
  121.     int x, y;
  122.     float hx, hy;
  123.     unsigned char *cptr;
  124.  
  125.     b = (brush *)mymalloc(sizeof(brush));
  126.     b->xsize = round(dx);
  127.     if(b->xsize<1)
  128.        b->xsize = 1;
  129.     b->ysize = round(dy);
  130.     if(b->ysize<1)
  131.        b->ysize = 1;
  132.     b->xorg = b->xsize/2;
  133.     b->yorg = b->ysize/2;
  134.     b->mat = (unsigned char *)mymalloc(b->xsize*b->ysize*sizeof(unsigned char));
  135.     cptr = b->mat;
  136.     hx = (b->xsize-1)/2.0;
  137.     hy = (b->ysize-1)/2.0;
  138.     alpha = 255.0*alpha;
  139.     for(y=0; y<b->ysize; y++) {
  140.     for(x=0; x<b->xsize; x++) {
  141.         *cptr = noiseround(alpha*limit(brushfunc((x-hx)/b->xsize,(y-hy)/b->ysize)));
  142.         cptr++;
  143.     }
  144.     }
  145.     return b;
  146. }
  147.  
  148. void drawbrush(dest,fx,fy)
  149. canvas *dest;
  150. float fx, fy;
  151. {
  152.     int bxmin, bxmax;
  153.     int bymin, bymax;
  154.     int x, y;
  155.     unsigned long *dptr;
  156.     unsigned char *curc;
  157.     rct brect;
  158.     int ox, oy, nx;
  159.     unsigned char *mat;
  160.     brush *b;
  161.     
  162.     updatebrush(curwidth,can_curalpha*can_curalphascale);
  163.     b = curbrush;
  164.     if(!blendrow)
  165.     setblend(BLEND_RGB);
  166.     if(b->xsize&1)
  167.     ox = round(fx-0.5);
  168.     else
  169.     ox = round(fx);
  170.     if(b->ysize&1)
  171.     oy = round(fy-0.5);
  172.     else
  173.     oy = round(fy);
  174.     ox = ox-b->xorg;
  175.     oy = oy-b->yorg;
  176.     brect.xmin = ox;
  177.     brect.xmax = ox+b->xsize-1;
  178.     brect.ymin = oy;
  179.     brect.ymax = oy+b->ysize-1;
  180.     if (!rctinter(&dest->area,&brect,&brect))
  181.     return;
  182.     saverect(dest,&brect);
  183.     nx = brect.xmax-brect.xmin+1;
  184.     mat = b->mat+(brect.xmin-ox)+(brect.ymin-oy)*b->xsize;
  185.     for(y=brect.ymin; y<=brect.ymax; y++) {
  186.     blendrow(dest,mat,brect.xmin,y,nx,0); 
  187.     mat += b->xsize;
  188.     }
  189.     markdirty(dest,&brect,1);
  190. }
  191.  
  192. /*
  193.  *    rand stuff follows
  194.  *
  195.  *
  196.  */
  197. static initrand()
  198. {
  199.     int i;
  200.     float x, y, rad, sc;
  201.  
  202.     i = 0;
  203.     circpos = (float *)mymalloc(2*RANDTABSIZE*sizeof(float));
  204.     randtab = (float *)mymalloc(RANDTABSIZE*sizeof(float));
  205.     while(i<RANDTABSIZE) {
  206.     x = (frand()-0.5);
  207.     y = (frand()-0.5);
  208.     rad = fsqrt(x*x+y*y);
  209.     if(rad <= 0.5) {
  210.         sc = fsqrt(rad*2.0);        /* warp to put more in center */
  211.         circpos[2*i+0] = sc*x;
  212.         circpos[2*i+1] = sc*y;
  213.         i++;
  214.     }
  215.     }
  216.     for(i=0; i<RANDTABSIZE; i++)
  217.     randtab[i] = (frand()-0.5);
  218. }
  219.  
  220. void getcircpos(x,y)
  221. float *x, *y;
  222. {
  223.     int ind;
  224.  
  225.     if(!randfirsted) {
  226.     initrand();
  227.         randfirsted = 1;
  228.     }
  229.     qp++;
  230.     if(qp == RANDTABSIZE)
  231.     qp = 0;
  232.     *x = circpos[2*qp+0];
  233.     *y = circpos[2*qp+1];
  234. }
  235.  
  236. float qrand()
  237. {
  238.     if(!randtab) 
  239.     initrand();
  240.     qp++;
  241.     if(qp == RANDTABSIZE)
  242.     qp = 0;
  243.     return randtab[qp];
  244. }
  245.  
  246.  
  247. int getqrandstate()
  248. {
  249.     return qp;
  250. }
  251.  
  252. int setqrandstate(s)
  253. int s;
  254. {
  255.     qp = s;
  256. }
  257.  
  258. void setcurwidth(width)
  259. float width;
  260. {
  261.     curwidth = width;
  262. }
  263.